package com.xiaoshuidi.cloud.module.member.service.user;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fadada.sdk.base.model.req.RegisterAccountParams;
import com.fadada.sdk.verify.model.req.FindPersonCertParams;
import com.fadada.sdk.verify.model.req.PersonVerifyUrlParams;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.fadada.core.FadadaAuthServiceApi;
import com.xiaoshuidi.cloud.framework.fadada.core.enums.AccountTypeEnum;
import com.xiaoshuidi.cloud.framework.fadada.core.enums.IdentTypeEnum;
import com.xiaoshuidi.cloud.framework.fadada.core.enums.PageModifyEnum;
import com.xiaoshuidi.cloud.framework.fadada.core.enums.VerifiedWayEnum;
import com.xiaoshuidi.cloud.framework.fadada.core.service.dto.PersonCertInfoRes;
import com.xiaoshuidi.cloud.framework.fadada.core.service.dto.VerifyUrlRes;
import com.xiaoshuidi.cloud.framework.redis.lock.DistributeLock;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.member.controller.app.auth.vo.FadadaCallbackReqVO;
import com.xiaoshuidi.cloud.module.member.controller.app.auth.vo.MemberAuthGetVerifyReqVO;
import com.xiaoshuidi.cloud.module.member.enums.AuthTypeEnum;
import com.xiaoshuidi.cloud.module.member.enums.AuthenticationProviderEnum;
import com.xiaoshuidi.cloud.module.member.enums.FadadaAuthStatusEnum;
import com.xiaoshuidi.cloud.module.member.mapper.MemberAuthenticationMapper;
import com.xiaoshuidi.cloud.module.member.pojo.user.MemberAuthentication;
import com.xiaoshuidi.cloud.module.member.pojo.user.MemberUser;
import com.xiaoshuidi.cloud.module.member.repository.MemberAuthenticationRepository;
import com.xiaoshuidi.cloud.module.member.repository.MemberUserRepository;
import com.xiaoshuidi.cloud.module.member.service.user.dto.MemberCustomerVerifyDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RefreshScope
@Slf4j
@Service
@RequiredArgsConstructor
public class MemberAuthenticationServiceImpl extends ServiceImpl<MemberAuthenticationMapper, MemberAuthentication> implements MemberAuthenticationService {
    private final MemberAuthenticationRepository memberAuthenticationRepository;

    private final MemberUserRepository memberUserRepository;

    @Value("${fadada.open_id_prefix}")
    private String OPEN_ID_PREFIX;

    @Value("${fadada.backend_callback_url}")
    private String BACKEND_CALLBACK_URL;

    @Value("${fadada.frontend_callback_url}")
    private String FRONTEND_CALLBACK_URL;

    private final MemberFadadaReplaceProperties memberFadadaReplaceProperties;

    private final FadadaAuthServiceApi fadadaAuthServiceApi;

    public static final String USER_AUTH_LOCK = "user:auth:lock";

    @Override
    public String getMemberVerifyUrl(MemberAuthGetVerifyReqVO reqVO) {

        try (DistributeLock lock = DistributeLock.getLock(USER_AUTH_LOCK + ":" + reqVO.getUserId())) {
            if (lock.tryLock()) {
                // 检查证件号是否已经注册,一个证件只能绑定一个手机号
                MemberUser memberUser = memberUserRepository.getUserByCardNo(reqVO.getCard(), reqVO.getPassPort(), reqVO.getHkCard(), reqVO.getTwCard());
                log.info("[实名认证]--注册信息:{}", JsonUtils.toJsonString(memberUser));
                log.info("[实名认证]--请求信息:{}", JsonUtils.toJsonString(reqVO));
                if(ObjectUtils.isNotEmpty(memberUser) && !memberUser.getMobile().equals(reqVO.getPhone())){
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "该证件号已认证,请不要重复认证!");
                }

                //1、 查询用户实名认证信息
                MemberAuthentication memberAuthentication = memberAuthenticationRepository.getMemberAuthentication(reqVO);
                if (ObjectUtils.isNotEmpty(memberAuthentication) && ObjectUtils.isNotEmpty(memberAuthentication.getIdauthStatus())
                        && memberAuthentication.getIdauthStatus().intValue() == FadadaAuthStatusEnum.APPROVED.getCode().intValue()) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "用户已认证成功!");
                }
                //如果没有用户认证信息
                if (ObjectUtils.isEmpty(memberAuthentication)) {
                    memberAuthentication = new MemberAuthentication();
                    memberAuthentication.setProvider(AuthenticationProviderEnum.FADADA.getCode());
                    memberAuthentication.setUserId(reqVO.getUserId());
//            memberAuthentication.setName(reqVO.getName());
//            memberAuthentication.setPhone(reqVO.getPhone());
//            memberAuthentication.setIdCard(reqVO.getCard());
                    memberAuthentication.setIdauthStatus(FadadaAuthStatusEnum.UNAUTHENTICATED.getCode());//初始赋值未认证
                }

                //注册法大大账号
                RegisterAccountParams params = new RegisterAccountParams();
                //唯一编号生成规则
                String openId = OPEN_ID_PREFIX + reqVO.getPhone() + reqVO.getUserId();
                params.setOpenId(openId);
                params.setAccountType(AccountTypeEnum.PERSONAL.getCode());
                String customerId = fadadaAuthServiceApi.accountRegister(params);
                if (StringUtils.isEmpty(customerId)) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "第三方认证平台获取客户编号异常!");
                }

                //获取个人实名认证地址
                PersonVerifyUrlParams verifyUrlParams = new PersonVerifyUrlParams();
                verifyUrlParams.setCustomerId(customerId);//设置客户编号
                verifyUrlParams.setMobile(reqVO.getPhone());
                if (reqVO.getAuthType().intValue() == AuthTypeEnum.THREEELEMENTS.getCode().intValue()) {
                    //三要素认证
                    verifyUrlParams.setVerifiedWay(VerifiedWayEnum.PURE_ELEMENT_3.getCode());
//            verifyUrlParams.setIsMinProgram("0");
                    verifyUrlParams.setIsMinProgram("3");
                } else if (reqVO.getAuthType().intValue() == AuthTypeEnum.FACE.getCode().intValue()) {
                    //人脸认证
//            verifyUrlParams.setVerifiedWay(VerifiedWayEnum.FACE_RECOGNITION.getCode());
//            verifyUrlParams.setIsMinProgram("3");
//        } else {
                    verifyUrlParams.setVerifiedWay(VerifiedWayEnum.ELEMENT_3_SUPPLEMENT.getCode());
                    verifyUrlParams.setIsMinProgram("3");
                    //是否需要上传身份照片 2-都不需要
                    verifyUrlParams.setIdPhotoOptional("2");
                }

                verifyUrlParams.setPageModify(PageModifyEnum.ALLOW.getCode());//是否允许用户页面修改 1允许 2不允许
                verifyUrlParams.setNotifyUrl(BACKEND_CALLBACK_URL);//法大大异步回调我们的地址
                verifyUrlParams.setReturnUrl(FRONTEND_CALLBACK_URL);
                verifyUrlParams.setCustomerName(reqVO.getName());
                //证件号
                if (reqVO.getIdentType().equals(IdentTypeEnum.ID_NO.getCode())) {
                    verifyUrlParams.setCustomerIdentType(reqVO.getIdentType());//是否支持其他证件类型
                    verifyUrlParams.setCustomerIdentNo(reqVO.getCard());
                } else if (reqVO.getIdentType().equals(IdentTypeEnum.PASSPORT_NO.getCode())) {
                    verifyUrlParams.setCustomerIdentType("1");//是否支持其他证件类型
                    verifyUrlParams.setCustomerIdentNo(reqVO.getPassPort());
                } else if (reqVO.getIdentType().equals(IdentTypeEnum.HOME_VISITING_NO.getCode())) {
                    verifyUrlParams.setCustomerIdentType("1");//是否支持其他证件类型
                    verifyUrlParams.setCustomerIdentNo(reqVO.getHkCard());
                } else if (reqVO.getIdentType().equals(IdentTypeEnum.TAIWANESE_SYNDROME_NO.getCode())) {
                    verifyUrlParams.setCustomerIdentType("1");//是否支持其他证件类型
                    verifyUrlParams.setCustomerIdentNo(reqVO.getTwCard());
                }
                //证件类型
                verifyUrlParams.setCertType(reqVO.getIdentType());
                //认证成功后自动绑定实名信息
                verifyUrlParams.setCertFlag("1");


                log.info("请求法大大获取实名认证地址，请求参数：{}", JSONObject.toJSONString(verifyUrlParams));
                VerifyUrlRes personVerifyUrl = fadadaAuthServiceApi.getPersonVerifyUrl(verifyUrlParams);
                log.info("请求法大大获取实名认证地址，返回参数：{}", JSONObject.toJSONString(personVerifyUrl));
                if (ObjectUtils.isNotEmpty(personVerifyUrl)) {
                    String url = personVerifyUrl.getUrl();//获取个人认证地址
                    //新增认证记录
                    memberAuthentication.setTransactionNo(personVerifyUrl.getTransactionNo());
                    memberAuthentication.setSignatureCode(customerId);
                    memberAuthentication.setFadadaId(openId);
                    memberAuthentication.setAuthType(reqVO.getAuthType());
//            MemberAuthentication auth = memberAuthenticationRepository.getMemberAuthenticationByCustomerId(customerId);
                    if (memberAuthentication != null && ObjectUtils.isNotEmpty(memberAuthentication.getId())) {
//                BeanUtils.copyProperties(memberAuthentication, auth);
                        memberAuthenticationRepository.updateById(memberAuthentication);
                    } else {
                        memberAuthenticationRepository.save(memberAuthentication);
                    }

                    // 替换法大大实名认证的URL
                    log.info("用户实名认证，读取到的配置：{}", JSONObject.toJSONString(memberFadadaReplaceProperties));
                    if (ObjectUtils.isNotEmpty(memberFadadaReplaceProperties)){
                        List<MemberCustomerVerifyDTO> memberCustomerVerifyList = memberFadadaReplaceProperties.getMemberCustomerVerifyList();
                        if (CollectionUtils.isNotEmpty(memberCustomerVerifyList)){
                            //获取getTenantId
                            Long tenantId = SecurityFrameworkUtils.getLoginUser().getTenantId();
                            MemberCustomerVerifyDTO defaultCustomerVerify = memberCustomerVerifyList.stream().filter(m -> "0".equals(m.getTenantId())).findFirst().orElse(null);
                            boolean verifyFlag = true;
                            for (MemberCustomerVerifyDTO memberCustomerVerifyDTO : memberCustomerVerifyList) {
                                if (String.valueOf(tenantId).equals(memberCustomerVerifyDTO.getTenantId())){
                                    url = url.replace(memberCustomerVerifyDTO.getTargetUrl(), memberCustomerVerifyDTO.getReplaceUrl());
                                    verifyFlag = false;
                                }
                            }
                            if (verifyFlag && ObjectUtils.isNotEmpty(defaultCustomerVerify)){
                                url = url.replace(defaultCustomerVerify.getTargetUrl(), defaultCustomerVerify.getReplaceUrl());
                            }
                            log.info("用户实名认证，最后替换完成的地址:{}", url);
                        }
                    }
//                    //获取getTenantId
//                    Long tenantId = SecurityFrameworkUtils.getLoginUser().getTenantId();
//                    if (tenantId.intValue() == 3992 || tenantId.intValue() == 10000) {
//                        url = url.replace("https://realnameverify.fadada.com", "https://realnameverify05.fadada.com");
//                    } else {
//                        url = url.replace("https://realnameverify.fadada.com", "https://realnameverify04.fadada.com");
//                    }

                    return url;
                } else {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "第三方认证平台获取个人认证地址异常!");
                }
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean handlerFadadaCallBack(FadadaCallbackReqVO reqVO) {
        log.info("法大大实名认证的回调，参数：{}", JSONObject.toJSONString(reqVO));
        //查询本地实名认证记录
        MemberAuthentication memberAuthentication = memberAuthenticationRepository.getMemberAuthenticationByCustomerId(reqVO.getCustomerId());
        if (ObjectUtils.isNotEmpty(memberAuthentication)) {
            //更新本地实名认证状态以及会员表里的实名认证状态
            LambdaUpdateWrapper<MemberAuthentication> wrapper = new LambdaUpdateWrapper<MemberAuthentication>()
                    .eq(MemberAuthentication::getId, memberAuthentication.getId())
                    .set(MemberAuthentication::getIdauthStatus, reqVO.getStatus().intValue());
            memberAuthenticationRepository.update(null, wrapper);

            //如何实名认证成功，从法大大上拉取实名认证信息
            if (reqVO.getStatus().intValue() == FadadaAuthStatusEnum.APPROVED.getCode().intValue()) {

                FindPersonCertParams findPersonCertParams = new FindPersonCertParams();
                findPersonCertParams.setVerifiedSerialNo(memberAuthentication.getTransactionNo());
                PersonCertInfoRes personCertInfo = null;
                try {
                    log.info("法大大实名认证的回调成功，查询用户信息，请求参数：{}", JSONObject.toJSONString(findPersonCertParams));
                    personCertInfo = fadadaAuthServiceApi.findPersonCertInfo(findPersonCertParams);
                    log.info("法大大实名认证的回调成功，查询用户信息，返回参数：{}", JSONObject.toJSONString(personCertInfo));
                } catch (Exception e) {
                    log.error("用户实名成功，查询实名信息，更新用户数据失败，用户实名数据：{}", JSONObject.toJSONString(memberAuthentication));
                }
                //2.更新人员表认证状态以及补全用户信息
                memberUserRepository.updateMemberUserAuthStatus(memberAuthentication, personCertInfo.getPerson());

            }
        } else {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "法大大回调更新认证状态未查询到本地认证记录！");
        }
        return null;
    }

    @Override
    public void deleteUser(Long id) {
        this.baseMapper.deleteUser(id);
    }
}
